package com.ymx.darling.transaction.jdbc;

import com.ymx.darling.exception.ExceptionFactory;
import com.ymx.darling.log.Log;
import com.ymx.darling.log.LogFactory;
import com.ymx.darling.transaction.Transaction;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * Darling的jdbc事务处理
 * @author 爱java的小于
 */
public class JdbcTransaction implements Transaction {
    private final Log logger = LogFactory.getLog(JdbcTransaction.class);
    private final DataSource dataSource;
    private final boolean autoCommit;
    private Connection connection;

    public JdbcTransaction(DataSource dataSource, boolean autoCommit) {
        this.dataSource = dataSource;
        this.autoCommit = autoCommit;
    }

    @Override
    public boolean getAutoCommit(){
        return this.autoCommit;
    }

    @Override
    public void commit(){
        try {
            if (this.connection != null && !this.connection.getAutoCommit()) {
                this.connection.commit();
                if (this.logger.isDebugEnabled()) {
                    logger.debug(String.format("数据库连接提交: [%s]", this.connection));
                }
            }
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("事务提交时出现异常", e);
        }
    }

    @Override
    public boolean isClose() {
        try {
            return this.connection != null && this.connection.isClosed();
        } catch (Exception var2) {
            throw ExceptionFactory.wrapException("判断连接是否关闭时发生异常", var2);
        }
    }

    @Override
    public void close(){
        try {
            if (this.connection != null) {
                this.resetAutoCommit();
                this.connection.close();
                if (this.logger.isDebugEnabled()) {
                    logger.debug(String.format("数据库连接已归还至连接池: [%s]", this.connection));
                }
            }
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("归还数据库连接时发生异常", e);
        }
    }


    /**
     * 重置连接自动提交状态
     */
    private void resetAutoCommit() {
        try {
            if (!this.connection.getAutoCommit()) {
                if (logger.isDebugEnabled()) {
                    logger.debug("正在将JDBC数据库连接[" + this.connection + "]的自动提交(autoCommit)属性重置为true");
                }
                this.connection.setAutoCommit(true);
            }
        } catch (Exception var2) {
            if (logger.isDebugEnabled()) {
                logger.debug("在关闭数据库连接前, 将自动提交(autoCommit)属性重置为true时出现异常。错误原因: " + var2);
            }
        }
    }


    @Override
    public void rollBack(){
        try {
            if (this.connection != null) {
                this.connection.rollback();
                if (this.logger.isDebugEnabled()) {
                    logger.debug(String.format("执行数据库连接回滚: [%s]", this.connection));
                }
            }
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("事务回滚时发生异常", e);
        }
    }

    @Override
    public Connection getConnection(){
        try {
            if (this.connection == null) {
                this.connection = dataSource.getConnection();
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug(String.format("从数据库连接池移除连接: [%s]", this.connection));                }
                if (this.autoCommit != connection.getAutoCommit()) {
                    this.setAutoCommit(this.autoCommit);
                }
            } else {
                if (this.connection.isClosed()) {
                    throw new SQLException(String.format("数据库连接[%s]已关闭，不能重复使用", this.connection));
                }
            }
            return this.connection;
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("获取数据库连接时发生异常", e);
        }
    }

    /**
     * 设置事务提交方式
     * @param autoCommit true 自动提交 false 手动提交
     * @throws SQLException 可能会抛出此异常
     */
    private void setAutoCommit(boolean autoCommit)throws SQLException {
        if (this.connection.getAutoCommit() != autoCommit) {
            this.connection.setAutoCommit(autoCommit);
        }
        if (logger.isDebugEnabled()) {
            this.logger.debug(String.format("数据库连接自动提交模式已设置为%s：[%s]", autoCommit, this.connection));
        }
    }
}
